﻿using System.Text.Json;
using System.Text.Json.Serialization;
using RotovapPlatform.Domain.Business.Storage.Entities.Base;
using RotovapPlatform.Domain.Business.Storage.Entities.Bottles;
using RotovapPlatform.Domain.Business.Storage.Entities;
using RotovapPlatform.Domain.Business.Storage.Entities.Grippers;

namespace RotovapPlatform.Infrastructure.Common.Json
{
	/// <summary>
	/// IStorageItem接口的JSON转换器
	/// 用于解决接口类型的序列化和反序列化问题
	/// </summary>
	public class StorageItemJsonConverter : JsonConverter<IStorageItem>
	{
		// 已知的IStorageItem实现类型映射
		private static readonly Dictionary<string, Type> _typeMapping = new()
		{
			{ "RotovapBottle", typeof(RotovapBottle) },
			{ "CentrifugeBottle", typeof(CentrifugeBottle) },
			{ "SampleBottle", typeof(SampleBottle) },
			{ "Gripper", typeof(Gripper) }
		};

		// ItemType到具体类型的映射
		private static readonly Dictionary<int, Type> _itemTypeMapping = new()
		{
			{ 0, typeof(RotovapBottle) }, // ItemType.Rotovap_500ml
            { 1, typeof(RotovapBottle) }, // ItemType.Rotovap_1000ml
            { 2, typeof(CentrifugeBottle) }, // ItemType.CentrifugeBottle_500ml
            { 3, typeof(SampleBottle) }, // ItemType.SampleBottle_8ml
            { 4, typeof(Gripper) }, // ItemType.NormalGripper
            { 5, typeof(Gripper) }  // ItemType.RotovapGripper
        };

		public override IStorageItem? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
		{
			// 首先尝试读取为JsonDocument以获取类型信息
			using var jsonDoc = JsonDocument.ParseValue(ref reader);
			var rootElement = jsonDoc.RootElement;

			// 确定具体类型
			Type? concreteType = null;

			// 尝试从$type属性获取类型信息
			if (rootElement.TryGetProperty("$type", out var typeProperty))
			{
				string typeName = typeProperty.GetString()!;
				if (_typeMapping.TryGetValue(typeName, out var type))
				{
					concreteType = type;
				}
				else
				{
					throw new JsonException($"未知的存储项类型: {typeName}");
				}
			}
			// 尝试从Type属性获取类型信息
			else if (rootElement.TryGetProperty("Type", out var itemTypeProperty) &&
					 itemTypeProperty.TryGetInt32(out int itemTypeValue))
			{
				if (_itemTypeMapping.TryGetValue(itemTypeValue, out var type))
				{
					concreteType = type;
				}
				else
				{
					throw new JsonException($"未知的物品类型值: {itemTypeValue}");
				}
			}
			else
			{
				throw new JsonException("无法确定存储项的具体类型，缺少$type属性或Type属性");
			}

			// 创建临时选项，避免循环引用
			var newOptions = new JsonSerializerOptions(options);
			newOptions.Converters.Remove(this);

			// 使用原始JSON字符串和确定的具体类型进行反序列化
			string jsonString = rootElement.GetRawText();

			try
			{
				var item = (IStorageItem)JsonSerializer.Deserialize(jsonString, concreteType, newOptions)!;

				// 特殊处理RotovapBottle类型的1000ml设置
				if (item is RotovapBottle rotovapBottle &&
					rootElement.TryGetProperty("Type", out var typeValue) &&
					typeValue.TryGetInt32(out int bottleType))
				{
					Console.WriteLine($"反序列化RotovapBottle - 检测到瓶子类型值: {bottleType}");

					if (bottleType == 1) // ItemType.Rotovap_1000ml
					{
						Console.WriteLine("设置瓶子为1000ml类型");
						rotovapBottle.SetAs1000ml();
					}
					else if (bottleType == 0) // ItemType.Rotovap_500ml
					{
						Console.WriteLine("设置瓶子为500ml类型（默认）");
						rotovapBottle.SetAs500ml();
					}
				}

				return item;
			}
			catch (Exception ex)
			{
				throw new JsonException($"反序列化类型 {concreteType.Name} 失败: {ex.Message}", ex);
			}
		}

		public override void Write(Utf8JsonWriter writer, IStorageItem value, JsonSerializerOptions options)
		{
			// 获取具体类型的名称
			string typeName = value.GetType().Name;

			// 创建临时选项，避免循环引用
			var newOptions = new JsonSerializerOptions(options);
			newOptions.Converters.Remove(this);

			// 序列化对象
			var jsonString = JsonSerializer.Serialize(value, value.GetType(), newOptions);

			// 解析为JsonDocument以便添加类型信息
			using var jsonDoc = JsonDocument.Parse(jsonString);
			writer.WriteStartObject();

			// 添加类型信息
			writer.WriteString("$type", typeName);

			// 复制所有其他属性
			foreach (var property in jsonDoc.RootElement.EnumerateObject())
			{
				property.WriteTo(writer);
			}

			writer.WriteEndObject();
		}
	}
}